import type { AxiosError, AxiosResponse } from "axios";
import {
  DEFAULT_REQUEST_ERROR_CODE,
  DEFAULT_REQUEST_ERROR_MSG,
  ERROR_STATUS,
  NETWORK_ERROR_CODE,
  NETWORK_ERROR_MSG,
  REQUEST_TIMEOUT_CODE,
  REQUEST_TIMEOUT_MSG,
} from ".";
import { showErrorMsg } from "./msg";
import { RequestConfig, RequestResult } from "@/types/custom/request";

type ErrorStatus = keyof typeof ERROR_STATUS;

/**
 * 处理axios请求失败的错误
 * @param axiosError - 错误
 */
export function handleAxiosError({ code, message, response }: AxiosError) {
  const error: Service.RequestError = {
    type: "axios",
    code: DEFAULT_REQUEST_ERROR_CODE,
    msg: DEFAULT_REQUEST_ERROR_MSG,
  };

  // 不需要错误提示
  const config = response?.config as RequestConfig;
  if (config?.noNeedTip) return error;

  // 网路错误
  if (!window.navigator.onLine || message === "Network Error") {
    Object.assign(error, { code: NETWORK_ERROR_CODE, msg: NETWORK_ERROR_MSG });
  }
  // 超时错误
  else if (code === "ECONNABORTED" && message.includes("timeout")) {
    Object.assign(error, { code: REQUEST_TIMEOUT_CODE, msg: REQUEST_TIMEOUT_MSG });
  }
  // 请求不成功的错误
  else if (response) {
    const errorCode = (response?.status as ErrorStatus) || "DEFAULT";
    const msg = ERROR_STATUS[errorCode];
    Object.assign(error, { code: errorCode, msg });
  }

  showErrorMsg(error);

  return error;
}

/**
 * 处理请求成功后的错误
 * @param response - 请求的响应
 */
export function handleResponseError({ status, config }: AxiosResponse) {
  const error: Service.RequestError = {
    type: "axios",
    code: DEFAULT_REQUEST_ERROR_CODE,
    msg: DEFAULT_REQUEST_ERROR_MSG,
  };

  // 不需要错误提示
  const { noNeedTip } = config as RequestConfig;
  if (noNeedTip) return error;

  if (!window.navigator.onLine) {
    // 网路错误
    Object.assign(error, { code: "NETWORK_ERROR", msg: "网络不可用~" });
  } else {
    // 请求成功的状态码非200的错误
    const errorCode = status as ErrorStatus;
    const msg = ERROR_STATUS[errorCode] || DEFAULT_REQUEST_ERROR_MSG;
    Object.assign(error, { type: "http", code: errorCode, msg });
  }

  showErrorMsg(error);

  return error;
}

/**
 * 处理后端返回的错误(业务错误)
 * @param backendResult - 后端接口的响应数据
 */
export function handleBackendError({ config, data }: AxiosResponse) {
  const result = data as RequestResult;
  const error: Service.RequestError = {
    type: "backend",
    code: result.code,
    msg: result.message,
  };

  // 不需要错误提示
  const { noNeedTip } = config as RequestConfig;
  if (noNeedTip) return error;

  showErrorMsg(error);

  return error;
}
